package com.nx.platform.es.biz.wrapper.parser;

import com.google.common.base.Strings;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.ImmutableTable;
import com.google.common.collect.Lists;
import com.google.common.collect.Table;

import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.google.common.base.Preconditions.checkArgument;

/**
 * @author
 * @since 2016年10月15日
 */
public enum StatementParsers implements StatementParser {

    Default {

        final Pattern STATEMENT_PATTERN = Pattern.compile("&*[\\w.]++!?+=[^&]*+(?:&++[\\w.]++!?+=[^&]*+)*+&*+");
        final Pattern FIELD_PATTERN = Pattern.compile("([\\w.]++)(!?+=)([^&]*+)");
        final Pattern PARAMS_PATTERN = Pattern.compile("^(param[a-z_]*+)([0-9]++)$");

        @Override
        public Table<String, StatementOperator, List<String>> parse(String statement) {
            if (Strings.isNullOrEmpty(statement) || "null".equals(statement)) {
                return ImmutableTable.of();
            }
            checkArgument(STATEMENT_PATTERN.matcher(statement).matches(), "format incorrect: " + statement);
            Matcher fieldMatcher = FIELD_PATTERN.matcher(statement);
            Table<String, StatementOperator, List<String>> result = HashBasedTable.create();
            while (fieldMatcher.find()) {
                String fieldName = fieldMatcher.group(1).toLowerCase();
                String operator = fieldMatcher.group(2);
                String fieldValue = fieldMatcher.group(3).trim();
                StatementOperator op = StatementOperator.value(operator);
                if ("".equals(fieldValue)) {
                    continue;
                }
                Matcher paramsMatcher = PARAMS_PATTERN.matcher(fieldName);
                // 普通变量名字不能与params类型变量格式相同
                if (paramsMatcher.find()) {
                    String paramFieldName = paramsMatcher.group(1);
                    String paramFieldKey = paramsMatcher.group(2);
                    List<String> paramList = result.get(paramFieldName, op);
                    String keyvalue = paramFieldKey + "," + fieldValue;
                    if (paramList == null) {
                        paramList = Lists.newLinkedList();
                        paramList.add(keyvalue);
                        result.put(paramFieldName, op, paramList);
                    } else {
                        paramList.add(keyvalue);
                    }
                } else {
                    List<String> paramList = result.get(fieldName, op);
                    if (paramList == null) {
                        paramList = Lists.newLinkedList();
                        paramList.add(fieldValue);
                        result.put(fieldName, op, paramList);
                    } else {
                        paramList.add(fieldValue);
                    }
                }
            }
            return result;
        }

    }

}
